package main

import (
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"net/http"
	"runtime"
	"sync"
	"time"
)

type Collector struct {
	// HTTP请求相关指标
	requestCounter  *prometheus.CounterVec
	requestDuration *prometheus.HistogramVec
	requestInFlight *prometheus.GaugeVec

	// 系统资源指标
	cpuUsage       *prometheus.GaugeVec
	memoryUsage    *prometheus.GaugeVec
	goroutineCount prometheus.Gauge

	// 业务指标
	businessCounter *prometheus.CounterVec
	queueLength     *prometheus.GaugeVec

	// 错误指标
	errorCounter *prometheus.CounterVec

	mu sync.RWMutex
}

func NewCollector(namespace string) *Collector {
	return &Collector{
		requestCounter: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: namespace,
				Name:      "http_requests_total",
				Help:      "Total number of HTTP requests",
			},
			[]string{"method", "path", "status"},
		),

		requestDuration: promauto.NewHistogramVec(
			prometheus.HistogramOpts{
				Namespace: namespace,
				Name:      "http_request_duration_seconds",
				Help:      "HTTP request duration in seconds",
				Buckets:   []float64{0.1, 0.3, 0.5, 0.7, 0.9, 1.0, 1.5, 2.0},
			},
			[]string{"method", "path"},
		),

		requestInFlight: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Name:      "http_requests_in_flight",
				Help:      "Current number of HTTP requests being processed",
			},
			[]string{"method"},
		),

		cpuUsage: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Name:      "cpu_usage_percent",
				Help:      "Current CPU usage percentage",
			},
			[]string{"core"},
		),

		memoryUsage: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Name:      "memory_usage_bytes",
				Help:      "Current memory usage in bytes",
			},
			[]string{"type"},
		),

		goroutineCount: promauto.NewGauge(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Name:      "goroutine_count",
				Help:      "Current number of goroutines",
			},
		),

		businessCounter: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: namespace,
				Name:      "business_operations_total",
				Help:      "Total number of business operations",
			},
			[]string{"operation", "status"},
		),

		queueLength: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Namespace: namespace,
				Name:      "queue_length",
				Help:      "Current queue length",
			},
			[]string{"queue"},
		),

		errorCounter: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Namespace: namespace,
				Name:      "errors_total",
				Help:      "Total number of errors",
			},
			[]string{"type"},
		),
	}
}

// RecordRequest 记录HTTP请求
func (c *Collector) RecordRequest(method, path string, status int, duration time.Duration) {
	c.requestCounter.WithLabelValues(method, path, string(status)).Inc()
	c.requestDuration.WithLabelValues(method, path).Observe(duration.Seconds())
}

// TrackInFlightRequests 跟踪正在处理的请求
func (c *Collector) TrackInFlightRequests(method string, delta int) {
	c.requestInFlight.WithLabelValues(method).Add(float64(delta))
}

// UpdateCPUUsage 更新CPU使用率
func (c *Collector) UpdateCPUUsage(core string, usage float64) {
	c.cpuUsage.WithLabelValues(core).Set(usage)
}

// UpdateMemoryUsage 更新内存使用情况
func (c *Collector) UpdateMemoryUsage(memType string, bytes float64) {
	c.memoryUsage.WithLabelValues(memType).Set(bytes)
}

// UpdateGoroutineCount 更新goroutine数量
func (c *Collector) UpdateGoroutineCount(count int64) {
	c.goroutineCount.Set(float64(count))
}

// RecordBusinessOperation 记录业务操作
func (c *Collector) RecordBusinessOperation(operation, status string) {
	c.businessCounter.WithLabelValues(operation, status).Inc()
}

// UpdateQueueLength 更新队列长度
func (c *Collector) UpdateQueueLength(queue string, length int) {
	c.queueLength.WithLabelValues(queue).Set(float64(length))
}

// RecordError 记录错误
func (c *Collector) RecordError(errorType string) {
	c.errorCounter.WithLabelValues(errorType).Inc()
}

var collector = NewCollector("Test")

func example1(c *gin.Context) {
	// 记录请求开始时间
	start := time.Now()
	time.Sleep(5 * time.Second)

	// 记录正在处理的请求
	collector.TrackInFlightRequests(c.Request.Method, 1)
	defer collector.TrackInFlightRequests(c.Request.Method, -1)

	// 计算处理时间
	duration := time.Since(start)
	// 记录请求指标
	collector.RecordRequest(c.Request.Method, c.FullPath(), c.Writer.Status(), duration)
	collector.UpdateGoroutineCount(int64(runtime.NumGoroutine()))

	c.JSON(http.StatusOK, "response")

}

func main() {
	r := gin.Default()
	r.GET("/metrics", gin.WrapH(promhttp.Handler()))

	// 创建示例API端点
	r.GET("/api/example", example1)

	r.Run("0.0.0.0:8082")

}
